#include "qxtglobalshortcut_p.h"
/****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**     * Redistributions of source code must retain the above copyright
**       notice, this list of conditions and the following disclaimer.
**     * Redistributions in binary form must reproduce the above copyright
**       notice, this list of conditions and the following disclaimer in the
**       documentation and/or other materials provided with the distribution.
**     * Neither the name of the LibQxt project nor the
**       names of its contributors may be used to endorse or promote products
**       derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
** <http://libqxt.org>  <foundation@libqxt.org>
*****************************************************************************/

#include <qt_windows.h>


#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
bool QxtGlobalShortcutPrivate::eventFilter(void* message)
{
#else
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
    void * message, long * result)
{
    Q_UNUSED(eventType);
    Q_UNUSED(result);
#endif
    MSG* msg = static_cast<MSG*>(message);
    if (msg->message == WM_HOTKEY)
    {
        const quint32 keycode = HIWORD(msg->lParam);
        const quint32 modifiers = LOWORD(msg->lParam);
        activateShortcut(keycode, modifiers);
    }

#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
    return prevEventFilter ? prevEventFilter(message) : false;
#else
	return false;
#endif
}
quint32 QxtGlobalShortcutPrivate::qNativeModifiers(quint32 modifiers)
{
	// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
	quint32 native = 0;
	if (modifiers & MOD_SHIFT)
		native |= Qt::ShiftModifier;
	if (modifiers & MOD_CONTROL)
		native |= Qt::ControlModifier;
	if (modifiers & MOD_ALT)
		native |= Qt::AltModifier;
	if (modifiers & MOD_WIN)
		native |= Qt::MetaModifier;
	// TODO: resolve these?
	//if (modifiers & Qt::KeypadModifier)
	//if (modifiers & Qt::GroupSwitchModifier)
	return native;
}

quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
{
    // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
    quint32 native = 0;
    if (modifiers & Qt::ShiftModifier)
        native |= MOD_SHIFT;
    if (modifiers & Qt::ControlModifier)
        native |= MOD_CONTROL;
    if (modifiers & Qt::AltModifier)
        native |= MOD_ALT;
    if (modifiers & Qt::MetaModifier)
        native |= MOD_WIN;
    // TODO: resolve these?
    //if (modifiers & Qt::KeypadModifier)
    //if (modifiers & Qt::GroupSwitchModifier)
    return native;
}
quint32 QxtGlobalShortcutPrivate::qNativeKeycode(quint32 key)
{
	switch (key)
	{
	case VK_ESCAPE:
		return Qt::Key_Escape;
	case VK_TAB:
	case Qt::Key_Backtab:
		return Qt::Key_Tab;
	case VK_BACK:
		return Qt::Key_Backspace;
	case VK_RETURN:
	case Qt::Key_Enter:
		return Qt::Key_Return;
	case VK_INSERT:
		return Qt::Key_Insert;
	case VK_DELETE:
		return Qt::Key_Delete;
	case VK_PAUSE:
		return Qt::Key_Pause;
	case VK_PRINT:
		return Qt::Key_Print;
	case VK_CLEAR:
		return Qt::Key_Clear;
	case VK_HOME:
		return Qt::Key_Home;
	case VK_END:
		return Qt::Key_End;
	case VK_LEFT:
		return Qt::Key_Left;
	case VK_UP:
		return Qt::Key_Up;
	case VK_RIGHT:
		return Qt::Key_Right;
	case VK_DOWN:
		return Qt::Key_Down;
	case VK_PRIOR:
		return Qt::Key_PageUp;
	case VK_NEXT:
		return Qt::Key_PageDown;
	case VK_F1:
		return Qt::Key_F1;
	case VK_F2:
		return Qt::Key_F2;
	case VK_F3:
		return Qt::Key_F3;
	case VK_F4:
		return Qt::Key_F4;
	case VK_F5:
		return Qt::Key_F5;
	case VK_F6:
		return Qt::Key_F6;
	case VK_F7:
		return Qt::Key_F7;
	case VK_F8:
		return Qt::Key_F8;
	case VK_F9:
		return Qt::Key_F9;
	case VK_F10:
		return Qt::Key_F10;
	case VK_F11:
		return Qt::Key_F11;
	case VK_F12:
		return Qt::Key_F12;
	case VK_F13:
		return Qt::Key_F13;
	case VK_F14:
		return Qt::Key_F14;
	case VK_F15:
		return Qt::Key_F15;
	case VK_F16:
		return Qt::Key_F16;
	case VK_F17:
		return Qt::Key_F17;
	case VK_F18:
		return Qt::Key_F18;
	case VK_F19:
		return Qt::Key_F19;		
	case VK_F20:
		return Qt::Key_F20;
	case VK_F21:
		return Qt::Key_F21;
	case VK_F22:
		return Qt::Key_F22;
	case VK_F23:
		return Qt::Key_F23;
	case VK_F24:
		return Qt::Key_F24;
	case VK_SPACE:
		return Qt::Key_Space;
	case VK_MULTIPLY:
		return Qt::Key_Asterisk;
	case VK_ADD:
		return Qt::Key_Plus;
	case VK_SEPARATOR:
		return Qt::Key_Comma;
	case VK_SUBTRACT:
		return Qt::Key_Minus;
	case VK_DIVIDE:
		return Qt::Key_Slash;
	case VK_MEDIA_NEXT_TRACK:
		return Qt::Key_MediaNext;
	case VK_MEDIA_PREV_TRACK:
		return Qt::Key_MediaPrevious;
	case VK_MEDIA_PLAY_PAUSE:
		return Qt::Key_MediaPlay;
	case VK_MEDIA_STOP:
		return Qt::Key_MediaStop;
		// couldn't find those in VK_*
		//case Qt::Key_MediaLast:
		//case Qt::Key_MediaRecord:
	case VK_VOLUME_DOWN:
		return Qt::Key_VolumeDown;
	case VK_VOLUME_UP:
		return Qt::Key_VolumeUp;
	case VK_VOLUME_MUTE:
		return Qt::Key_VolumeMute;

		// numbers
	case Qt::Key_0:
	case Qt::Key_1:
	case Qt::Key_2:
	case Qt::Key_3:
	case Qt::Key_4:
	case Qt::Key_5:
	case Qt::Key_6:
	case Qt::Key_7:
	case Qt::Key_8:
	case Qt::Key_9:
		return key;

		// letters
	case Qt::Key_A:
	case Qt::Key_B:
	case Qt::Key_C:
	case Qt::Key_D:
	case Qt::Key_E:
	case Qt::Key_F:
	case Qt::Key_G:
	case Qt::Key_H:
	case Qt::Key_I:
	case Qt::Key_J:
	case Qt::Key_K:
	case Qt::Key_L:
	case Qt::Key_M:
	case Qt::Key_N:
	case Qt::Key_O:
	case Qt::Key_P:
	case Qt::Key_Q:
	case Qt::Key_R:
	case Qt::Key_S:
	case Qt::Key_T:
	case Qt::Key_U:
	case Qt::Key_V:
	case Qt::Key_W:
	case Qt::Key_X:
	case Qt::Key_Y:
	case Qt::Key_Z:
		return key;

	default:
		return 0;
	}
}

quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{
    switch (key)
    {
    case Qt::Key_Escape:
        return VK_ESCAPE;
    case Qt::Key_Tab:
    case Qt::Key_Backtab:
        return VK_TAB;
    case Qt::Key_Backspace:
        return VK_BACK;
    case Qt::Key_Return:
    case Qt::Key_Enter:
        return VK_RETURN;
    case Qt::Key_Insert:
        return VK_INSERT;
    case Qt::Key_Delete:
        return VK_DELETE;
    case Qt::Key_Pause:
        return VK_PAUSE;
    case Qt::Key_Print:
        return VK_PRINT;
    case Qt::Key_Clear:
        return VK_CLEAR;
    case Qt::Key_Home:
        return VK_HOME;
    case Qt::Key_End:
        return VK_END;
    case Qt::Key_Left:
        return VK_LEFT;
    case Qt::Key_Up:
        return VK_UP;
    case Qt::Key_Right:
        return VK_RIGHT;
    case Qt::Key_Down:
        return VK_DOWN;
    case Qt::Key_PageUp:
        return VK_PRIOR;
    case Qt::Key_PageDown:
        return VK_NEXT;
    case Qt::Key_F1:
        return VK_F1;
    case Qt::Key_F2:
        return VK_F2;
    case Qt::Key_F3:
        return VK_F3;
    case Qt::Key_F4:
        return VK_F4;
    case Qt::Key_F5:
        return VK_F5;
    case Qt::Key_F6:
        return VK_F6;
    case Qt::Key_F7:
        return VK_F7;
    case Qt::Key_F8:
        return VK_F8;
    case Qt::Key_F9:
        return VK_F9;
    case Qt::Key_F10:
        return VK_F10;
    case Qt::Key_F11:
        return VK_F11;
    case Qt::Key_F12:
        return VK_F12;
    case Qt::Key_F13:
        return VK_F13;
    case Qt::Key_F14:
        return VK_F14;
    case Qt::Key_F15:
        return VK_F15;
    case Qt::Key_F16:
        return VK_F16;
    case Qt::Key_F17:
        return VK_F17;
    case Qt::Key_F18:
        return VK_F18;
    case Qt::Key_F19:
        return VK_F19;
    case Qt::Key_F20:
        return VK_F20;
    case Qt::Key_F21:
        return VK_F21;
    case Qt::Key_F22:
        return VK_F22;
    case Qt::Key_F23:
        return VK_F23;
    case Qt::Key_F24:
        return VK_F24;
    case Qt::Key_Space:
        return VK_SPACE;
    case Qt::Key_Asterisk:
        return VK_MULTIPLY;
    case Qt::Key_Plus:
        return VK_ADD;
    case Qt::Key_Comma:
        return VK_SEPARATOR;
    case Qt::Key_Minus:
        return VK_SUBTRACT;
    case Qt::Key_Slash:
        return VK_DIVIDE;
    case Qt::Key_MediaNext:
        return VK_MEDIA_NEXT_TRACK;
    case Qt::Key_MediaPrevious:
        return VK_MEDIA_PREV_TRACK;
    case Qt::Key_MediaPlay:
        return VK_MEDIA_PLAY_PAUSE;
    case Qt::Key_MediaStop:
        return VK_MEDIA_STOP;
        // couldn't find those in VK_*
        //case Qt::Key_MediaLast:
        //case Qt::Key_MediaRecord:
    case Qt::Key_VolumeDown:
        return VK_VOLUME_DOWN;
    case Qt::Key_VolumeUp:
        return VK_VOLUME_UP;
    case Qt::Key_VolumeMute:
        return VK_VOLUME_MUTE;

        // numbers
    case Qt::Key_0:
    case Qt::Key_1:
    case Qt::Key_2:
    case Qt::Key_3:
    case Qt::Key_4:
    case Qt::Key_5:
    case Qt::Key_6:
    case Qt::Key_7:
    case Qt::Key_8:
    case Qt::Key_9:
        return key;

        // letters
    case Qt::Key_A:
    case Qt::Key_B:
    case Qt::Key_C:
    case Qt::Key_D:
    case Qt::Key_E:
    case Qt::Key_F:
    case Qt::Key_G:
    case Qt::Key_H:
    case Qt::Key_I:
    case Qt::Key_J:
    case Qt::Key_K:
    case Qt::Key_L:
    case Qt::Key_M:
    case Qt::Key_N:
    case Qt::Key_O:
    case Qt::Key_P:
    case Qt::Key_Q:
    case Qt::Key_R:
    case Qt::Key_S:
    case Qt::Key_T:
    case Qt::Key_U:
    case Qt::Key_V:
    case Qt::Key_W:
    case Qt::Key_X:
    case Qt::Key_Y:
    case Qt::Key_Z:
        return key;

    default:
        return 0;
    }
}

bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods,void* pHwnd)
{
    return RegisterHotKey((HWND)pHwnd, nativeMods ^ nativeKey, nativeMods, nativeKey);
}

bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods,void* pHwnd)
{
    return UnregisterHotKey((HWND)pHwnd, nativeMods ^ nativeKey);
}
